package net.expectx.pay.gateway.controller;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import com.google.common.collect.Maps;
import io.swagger.annotations.ApiOperation;
import net.expectx.common.single.util.AesUtil;
import net.expectx.common.single.util.RequestUtil;
import net.expectx.pay.core.api.PaymentHandlerInterface;
import net.expectx.pay.core.common.EXPayResult;
import net.expectx.pay.core.service.provider.ProviderAliPayPageDriver;
import net.expectx.pay.core.service.provider.ProviderAliPayQrCodeDriver;
import net.expectx.pay.core.service.provider.ProviderAliPayWapDriver;
import net.expectx.pay.core.service.provider.ProviderWXPayQrCodeDriver;
import net.expectx.pay.gateway.common.AdminConstants;
import net.expectx.pay.gateway.common.AdminResult;
import net.expectx.pay.gateway.common.util.ExpectXUtil;
import net.expectx.pay.gateway.common.util.RedisUtil;
import net.expectx.pay.gateway.common.util.UserAgentUtil;
import net.expectx.pay.gateway.dao.bean.*;
import net.expectx.pay.gateway.rpc.api.MerchantPaymentConfigService;
import net.expectx.pay.gateway.rpc.api.PaymentChannelService;
import net.expectx.pay.gateway.rpc.api.ProductOrderHeaderService;
import net.expectx.pay.gateway.rpc.api.ProductOrderPaymentRecordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import redis.clients.jedis.Jedis;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("/pay")
public class PayController {
    @Autowired
    private ProductOrderHeaderService productOrderHeaderService;
    @Autowired
    private ProductOrderPaymentRecordService productOrderPaymentRecordService;
    @Autowired
    private MerchantPaymentConfigService merchantPaymentConfigService;
    @Autowired
    private PaymentChannelService paymentChannelService;
    @RequestMapping(value = "index")
    public String index(ModelMap map, HttpServletRequest request){
        map.put("HOST",AdminConstants.HOST);
        Map<String, String> params = Maps.newHashMapWithExpectedSize(7);
        /**
         * 检验参数
         */
        List<String>channelAttrs=new ArrayList<>();
        if (UserAgentUtil.isMobile(request)){
            channelAttrs.add("alipay_wap");
        }else{
            channelAttrs.add("alipay_qr");
            channelAttrs.add("wx_pub_qr");
        }

        AdminResult adminResult = calibrationParameters(request, params,channelAttrs);
        if (!adminResult.isSuccess()){
            map.put("dataResult",adminResult);
            return "errorPay";
        }

        if (adminResult.isSuccess()){
            Map<String, Object> resultData=(Map<String, Object>) adminResult.getData();
            List<MerchantPaymentConfig>merchantPaymentConfigs=(List<MerchantPaymentConfig>) resultData.get("merchantPaymentConfigs");
            MerchantUser merchantUser=(MerchantUser) resultData.get("merchantUser");
            map.put("merchantUser",merchantUser);
            Map<String, String> body =(Map<String, String>) resultData.get("body");
            adminResult = new AdminResult(productOrderHeaderService.createOrder(body));
            if (!adminResult.isSuccess()) {
                map.put("dataResult",adminResult);
                return "errorPay";
            }
            ProductOrderHeader orderHeader=(ProductOrderHeader) adminResult.getData();
            map.put("orderHeader",orderHeader);
            Jedis jedis= RedisUtil.getJedis();
            jedis.hset("EXPAY:productOrder",orderHeader.getOrderId(), JSONObject.toJSONString(orderHeader));
            jedis.close();
            map.put("merchantPaymentConfigs",merchantPaymentConfigs);
            if (UserAgentUtil.isMobile(request)){
                return "wapPay";
            }else{

                return "pcPay";
            }
        }else{
            return "wapPay";
        }


    }

    @RequestMapping(value = "{id}/{orderId}/generalQrCode")
    @ResponseBody
    public Object generalQrCode(@PathVariable(value = "id") Long id,@PathVariable(value = "orderId") String orderId, HttpServletRequest request){
        MerchantPaymentConfig merchantPaymentConfig=merchantPaymentConfigService.selectByPrimaryKey(id);
        String channelAttr=merchantPaymentConfig.getChannelAttr();
        PaymentHandlerInterface paymentHandlerInterface=null;
        Map<String, Object> payParams = new HashMap<String, Object>();
        ProductOrderHeaderExample productOrderHeaderExample=new ProductOrderHeaderExample();
        productOrderHeaderExample.createCriteria().andMerchantOrderIdEqualTo(orderId);
        List<ProductOrderHeader>productOrderHeaders=productOrderHeaderService.selectByExample(productOrderHeaderExample);
        if (productOrderHeaders.isEmpty()){
            return new AdminResult(false, 0, "参数被篡改了", null);
        }
        ProductOrderHeader productOrderHeader=productOrderHeaders.get(0);
        productOrderHeader.setChannelId(merchantPaymentConfig.getPaymentChannel());
        productOrderHeader.setNotifyUrl(merchantPaymentConfig.getNotifyUrl());
        productOrderHeaderService.updateByPrimaryKeySelective(productOrderHeader);
        if ("alipay_qr".equals(channelAttr)){
            /**
             * 支付宝扫码
             */
            paymentHandlerInterface=new ProviderAliPayQrCodeDriver(null);
            payParams.put("orderId",productOrderHeader.getOrderId());
            payParams.put("orderName",  productOrderHeader.getOrderName());
            payParams.put("orderDesc", productOrderHeader.getOrderDesc());
            payParams.put("totalAmount",  productOrderHeader.getGrandTotal().doubleValue());
            payParams.put("notifyUrl", AdminConstants.ALI_PAY_NOTIFY);
            payParams.put("authToken", merchantPaymentConfig.getAppId());
        }else  if ("wx_pub_qr".equals(channelAttr)){
            /**
             * 微信扫码
             */
            paymentHandlerInterface=new ProviderWXPayQrCodeDriver();
            payParams.put("subAppId",merchantPaymentConfig.getAppId());
            payParams.put("subMchId", merchantPaymentConfig.getMchId());
            payParams.put("notifyUrl", AdminConstants.WEI_XIN_PAY_NOTIFY);
            payParams.put("body",  productOrderHeader.getOrderName());
            payParams.put("outTradeNo",productOrderHeader.getOrderId());
            payParams.put("totalFee", productOrderHeader.getGrandTotal().doubleValue());
            payParams.put("createIp", RequestUtil.getIpAddr(request));
        }
        EXPayResult exPayResult=paymentHandlerInterface.doPay(payParams);
        if (exPayResult.isSuccess()){
            Map<String,String>map=(Map<String, String>) exPayResult.getData();
            map.put("channel",channelAttr);
        }

        return  exPayResult;


    }


    public AdminResult calibrationParameters(HttpServletRequest request, Map<String, String> params, List<String>channelAttrs) {
        try {
            AdminResult adminResult= ExpectXUtil.encrypt(request);
            if (!adminResult.isSuccess()){
                return  adminResult;
            }
            /*商户号*/
            String merchantNo = request.getParameter("merchantNo");
            /*应用号*/
            String applicationNo = request.getParameter("applicationNo");
            String merchantOrderId = request.getParameter("merchantOrderId");
            String orderName = request.getParameter("orderName");
            String orderDesc = request.getParameter("orderDesc");
            Long orderDate = Long.parseLong(request.getParameter("orderDate"));
            String tradeAmount = request.getParameter("tradeAmount");
            String sign = request.getParameter("sign");
            /**
             * 校验密钥
             */
            String privateKey = request.getHeader("privateKey");


            /**
             * 校验签名
             */
            Map<String, String> body = new HashMap<>(2);
            body.put("merchantNo", merchantNo);
            body.put("applicationNo", applicationNo);
            body.put("merchantOrderId", merchantOrderId);
            body.put("orderName", orderName);
            body.put("orderDesc", orderDesc);
            body.put("orderDate", orderDate.toString());
            body.put("tradeAmount", tradeAmount);
            for (Map.Entry<String, String> entry : params.entrySet()) {
                body.put(entry.getKey(), entry.getValue());
            }

            String s = WXPayUtil.generateSignature(body, privateKey, WXPayConstants.SignType.MD5);
            System.out.println("签名：" + s);
            System.out.println("获得签名：" + sign);

            if (!s.equals(sign)) {
                adminResult = new AdminResult(false, 0, "签名验证失败", null);
                return adminResult;
            }
            String currencyUom = "CNY";
            body.put("currencyUom", currencyUom);


            /**
             * 检验支付通道
             */
            PaymentChannelExample paymentChannelExample = new PaymentChannelExample();

            paymentChannelExample.createCriteria().andChannelAttrIn(channelAttrs);
            List<PaymentChannel> paymentChannels = paymentChannelService.selectByExample(paymentChannelExample);
            if (paymentChannels.isEmpty()) {
                adminResult = new AdminResult(false, 0, "支付通道参数错误", null);
                return adminResult;
            }
            PaymentChannel paymentChannel = paymentChannels.get(0);
            /**
             * 检验支付通道配置
             */
            MerchantPaymentConfigExample merchantPaymentConfigExample = new MerchantPaymentConfigExample();
            merchantPaymentConfigExample.createCriteria()
                    .andMerchantNoEqualTo(merchantNo)
                    .andApplicationNoEqualTo(applicationNo)
                    .andChannelAttrIn(channelAttrs);
            List<MerchantPaymentConfig> merchantPaymentConfigs = merchantPaymentConfigService.selectByExample(merchantPaymentConfigExample);
            if (merchantPaymentConfigs.isEmpty()) {
                adminResult = new AdminResult(false, 0, "商户号或应用号错误或" + paymentChannel.getName() + "未开通", null);
                return adminResult;
            }




            Map result = Maps.newHashMapWithExpectedSize(7);
            result.put("merchantPaymentConfigs", merchantPaymentConfigs);
            result.put("merchantUser", merchantPaymentConfigs.get(0).getMerchantUser());
            result.put("body", body);

            adminResult = new AdminResult(true, 200, "成功", result);
            return adminResult;
        } catch (Exception e) {
            e.printStackTrace();
            AdminResult adminResult = new AdminResult(false, 0, "系统错误或缺少参数", null);
            return adminResult;
        }

    }


    @ApiOperation(value = "支付")
    @PostMapping("doPay")
    public String doPay(ModelMap map, HttpServletRequest request, HttpServletResponse response) throws Exception {
        try {
            String orderId = request.getParameter("orderId");
            String channelId = request.getParameter("channelId");
            /**
             * 判断订单是否存在
             */
            ProductOrderHeaderExample productOrderHeaderExample = new ProductOrderHeaderExample();
            productOrderHeaderExample.createCriteria().andMerchantOrderIdEqualTo(orderId);
            List<ProductOrderHeader> productOrderHeaders = productOrderHeaderService.selectByExample(productOrderHeaderExample);
            if (productOrderHeaders.isEmpty()) {
                map.put("dataResult", new AdminResult(false, 0, "商户订单不存在", null));
                return "errorPay";
            }
            MerchantPaymentConfig merchantPaymentConfig=merchantPaymentConfigService.selectByPrimaryKey(Long.valueOf(channelId));
            if (merchantPaymentConfig==null) {
                map.put("dataResult", new AdminResult(false, 0, "暂无该支付通道", null));
                return "errorPay";
            }
            ProductOrderHeader orderHeader = productOrderHeaders.get(0);
            orderHeader.setChannelId(merchantPaymentConfig.getPaymentChannel());
            request.setAttribute("orderHeader", orderHeader);
            request.setAttribute("merchantPaymentConfig", merchantPaymentConfig);
            ProductOrderPaymentRecord orderPaymentRecord = orderHeader.getProductOrderPaymentRecord();
            if ("alipay_wap".equals(merchantPaymentConfig.getChannelAttr())) {
                orderPaymentRecord.setChannelPayway(channelId);
                orderPaymentRecord.setChannelPaywayName(merchantPaymentConfig.getPayWay());
                productOrderHeaderService.updateByPrimaryKeySelective(orderHeader);
                productOrderPaymentRecordService.updateByPrimaryKey(orderPaymentRecord);
                return "forward:doAliPay";
            }

            map.put("dataResult", new AdminResult(false, 0, "支付方式错误", null));
            return "errorPay";
        } catch (Exception e) {
            map.put("dataResult", new AdminResult(false, 0, "系统错误:" + e.getLocalizedMessage(), null));
            return "errorPay";
        }
    }

    @ApiOperation(value = "阿里支付")
    @PostMapping("doAliPay")
    @ResponseBody
    public void doAliPay(HttpServletRequest request, HttpServletResponse response) throws Exception {
        try {
            ProductOrderHeader orderHeader = (ProductOrderHeader) request.getAttribute("orderHeader");
            if (orderHeader == null) {
                throw new Exception("商户订单不存在或参数被篡改");
            }
            MerchantPaymentConfig merchantPaymentConfig =(MerchantPaymentConfig) request.getAttribute("merchantPaymentConfig");

            PaymentHandlerInterface paymentHandlerInterface;
            if (UserAgentUtil.isMobile(request)) {
                paymentHandlerInterface = new ProviderAliPayWapDriver(null);
            } else {
                paymentHandlerInterface = new ProviderAliPayPageDriver(null);
            }
            Map<String, Object> params = new HashMap<>(2);
            params.put("orderId", orderHeader.getOrderId());
            params.put("orderName", orderHeader.getOrderName());
            params.put("orderDesc", orderHeader.getOrderDesc());
            params.put("notifyUrl", AdminConstants.ALI_PAY_NOTIFY);
            params.put("returnUrl", AdminConstants.ALI_PAY_RETURN_URL);
            params.put("totalAmount", orderHeader.getGrandTotal());
            params.put("authToken", merchantPaymentConfig.getAppId());
            EXPayResult exPayResult = paymentHandlerInterface.doPay(params);
            System.out.println(exPayResult);
            String form = exPayResult.getData().toString();


            response.setContentType("text/html;charset=UTF-8");
            response.getWriter().write(form);
            response.getWriter().flush();
            response.getWriter().close();
        } catch (Exception e) {
            response.setContentType("text/html;charset=UTF-8");
            response.getWriter().write(e.getLocalizedMessage());
            response.getWriter().flush();
            response.getWriter().close();
        }
    }

}
